In [1]:
import pandas as pd
import numpy as np
import matplotlib
In [2]:
shotsdf = pd.read_csv('dat.csv')
shotsdf=shotsdf[shotsdf.SHOT_ZONE_BASIC!='Backcourt']
shotsdf=shotsdf[shotsdf.SHOT_ZONE_AREA!='Back court(BC)']
In [3]:
court_shapes = []

#Outer Lines
outer_lines_shape = dict(
    type='rect',
    xref='x',
    yref='y',
    x0='-250',
    y0='-47.5',
    x1='250',
    y1='422.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(outer_lines_shape)

#Hoop Shape
hoop_shape = dict(
    type='circle',
    xref='x',
    yref='y',
    x0='7.5',
    y0='7.5',
    x1='-7.5',
    y1='-7.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(hoop_shape)

#Basket Backboard
backboard_shape = dict(
    type='rect',
    xref='x',
    yref='y',
    x0='-30',
    y0='-7.5',
    x1='30',
    y1='-6.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    ),
    fillcolor='rgba(10, 10, 10, 1)'
)
 
court_shapes.append(backboard_shape)

#Outer Box of Three-Second Area
outer_three_sec_shape = dict(
    type='rect',
    xref='x',
    yref='y',
    x0='-80',
    y0='-47.5',
    x1='80',
    y1='143.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(outer_three_sec_shape)

#Inner Box of Three-Second Area
inner_three_sec_shape = dict(
    type='rect',
    xref='x',
    yref='y',
    x0='-60',
    y0='-47.5',
    x1='60',
    y1='143.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(inner_three_sec_shape)

#Three Point Line (Left)
left_line_shape = dict(
    type='line',
    xref='x',
    yref='y',
    x0='-220',
    y0='-47.5',
    x1='-220',
    y1='92.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(left_line_shape)

#Three Point Line (Right)
right_line_shape = dict(
    type='line',
    xref='x',
    yref='y',
    x0='220',
    y0='-47.5',
    x1='220',
    y1='92.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(right_line_shape)

#Three Point Line Arc
three_point_arc_shape = dict(
    type='path',
    xref='x',
    yref='y',
    path='M -220 92.5 C -70 300, 70 300, 220 92.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(three_point_arc_shape)

#Center Circle
center_circle_shape = dict(
    type='circle',
    xref='x',
    yref='y',
    x0='60',
    y0='482.5',
    x1='-60',
    y1='362.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(center_circle_shape)

#Restraining Circle
res_circle_shape = dict(
    type='circle',
    xref='x',
    yref='y',
    x0='20',
    y0='442.5',
    x1='-20',
    y1='402.5',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(res_circle_shape)

#Free Throw Circle
free_throw_circle_shape = dict(
    type='circle',
    xref='x',
    yref='y',
    x0='60',
    y0='200',
    x1='-60',
    y1='80',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1
    )
)
 
court_shapes.append(free_throw_circle_shape)

#Restricted Area
res_area_shape = dict(
    type='circle',
    xref='x',
    yref='y',
    x0='40',
    y0='40',
    x1='-40',
    y1='-40',
    line=dict(
        color='rgba(10, 10, 10, 1)',
        width=1,
        dash='dot'
    )
)
 
court_shapes.append(res_area_shape)
In [4]:
def getZoneText(team, zone_name):
    attempted = 0
    #Center Three Pointer
    if (zone_name == "center_3"):
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])
        
    #Left Center Three Pointer
    elif (zone_name == "left_center_3"):
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_AREA == 'Left Side Center(LC)') 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_AREA == 'Left Side Center(LC)') 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])

    #Right Center Three Pointer
    elif (zone_name == "right_center_3"):
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team)
                                & (shotsdf.SHOT_ZONE_AREA == 'Right Side Center(RC)') 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_AREA == 'Right Side Center(RC)') 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Above the Break 3')]['SHOT_MADE_FLAG'])

    #Left Corner Three Pointer
    elif (zone_name == "left_corner_3"):
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Left Corner 3')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Left Corner 3')]['SHOT_MADE_FLAG'])


    #Right Corner Three Pointer
    elif (zone_name == "right_corner_3"):    
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Right Corner 3')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Right Corner 3')]['SHOT_MADE_FLAG'])

    #Center Mid Range
    elif (zone_name == "center_mid"):  
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')]['SHOT_MADE_FLAG'])

    #Left Center Mid Range
    elif (zone_name == "left_center_mid"):  
        made = sum(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Left Side Center(LC)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                ((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Left Side Center(LC)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                     ((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])

    #Right Center Mid Range
    elif (zone_name == "right_center_mid"):  
        made = sum(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Right Side Center(RC)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                ((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Right Side Center(RC)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                     ((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])

    #Left Mid Range
    elif (zone_name == "left_mid"):  
        made = sum(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                ((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                     ((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Left Side(L)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])

    #Right Mid Range
    elif (zone_name == "right_mid"):  
        made = sum(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                ((shotsdf.TEAM_NAME ==team) 
                                 & (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                 & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[((shotsdf.TEAM_NAME ==team) 
                                      & (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'Mid-Range')) |
                                     ((shotsdf.TEAM_NAME ==team) & 
                                      (shotsdf.SHOT_ZONE_AREA == 'Right Side(R)') 
                                      & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)'))]['SHOT_MADE_FLAG'])

    #Paint (Not Restricted Area)
    elif (zone_name == "paint"):  
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_AREA == 'Center(C)') 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'In The Paint (Non-RA)')]['SHOT_MADE_FLAG'])

    #Restricted Area
    elif (zone_name == "restricted_area"):  
        made = sum(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                & (shotsdf.SHOT_ZONE_BASIC == 'Restricted Area')]['SHOT_MADE_FLAG'])
        attempted = len(shotsdf[(shotsdf.TEAM_NAME ==team) 
                                     & (shotsdf.SHOT_ZONE_BASIC == 'Restricted Area')]['SHOT_MADE_FLAG'])
    
    if (attempted == 0): return ''
    else: return "<b>{}-{}<br>{}</b>".format(made, attempted, round(made/attempted, 3)) 
In [5]:
def getZones():
    zone_shapes = []

    #Three Point Line Arc Top Left
    zone1 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M -250,92 L -220,92 C -187,140 -161,174 -80,228  L -95,350 L -250,350 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone1)

    #Three Point Line Arc Top Right
    zone2 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M 250,92 L 220,92 C 187,140 161,174 80,228  L 95,350 L 250,350 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone2)

    #Three Point Line Arc Top Center
    zone3 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M -80,228 C -50,240 0,266 80,228 L 95,350 L -95,350 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone3)

    #Three Point Line Left Corner
    zone4 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M -250,-47.5 L -220,-47.5 L -220,92 L -250,92 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone4)

    #Three Point Line Right Corner
    zone5 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M 250,-47.5 L 220,-47.5 L 220,92 L 250,92 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone5)

    #Under the basket
    zone6 = dict(
        type='path',
        xref='x',
        yref='y',
        path='M -40,-47.5 L -40,0 C -40,53 40,53 40,0 L 40,-47.5 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone6)

    #Paint
    zone7 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M -60,-47.5 L -40,-47.5 L -40,0 C -40,53 40,53 40,0 L 40,-47.5 L 60,-47.5 L 60,143.5 L -60,143.5 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone7)

    #Midrange Center
    zone8 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M -60,143.5 L -80,228 C -50,240 0,266 80,228 L 60,143.5 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone8)

    #Midrange Center Left
    zone8 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M -220,92 C -187,140 -161,174 -80,228 L -60,143.5 L -60,92 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone8)

    #Midrange Center Right
    zone9 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M 220,92 C 187,140 161,174 80,228 L 60,143.5 L 60,92 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone9)

    #Midrange Left
    zone10 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M -220,-47.5 L -220,92 L -60,92 L -60,-47.5 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone10)

    #Midrange Right
    zone11 = dict(    
        type='path',
        xref='x',
        yref='y',
        path='M 220,-47.5 L 220,92 L 60,92 L 60,-47.5 Z',
        line=dict(
            color='rgba(10, 10, 10, 1)',
            width=1
        )
    )

    zone_shapes.append(zone11)
    return zone_shapes
In [7]:
import plotly.graph_objs as go
from plotly.offline import iplot, init_notebook_mode
init_notebook_mode(connected=True)
def updateVisibility(selectedTeam):
    visibilityValues = []
    for team in list(shotsdf.TEAM_NAME.unique()):
        if team == selectedTeam:
            visibilityValues.append(True) #shot_trace_made
            visibilityValues.append(True) #shot_trace_missed
            visibilityValues.append(True) #shot_zone_text
        else:
            visibilityValues.append(False)
            visibilityValues.append(False)
            visibilityValues.append(False)
    return visibilityValues

zone_shapes = getZones()
data = []
buttons_data = []
for team in list(shotsdf.TEAM_NAME.unique()):
    shot_trace_made = go.Scatter(
        x = shotsdf[(shotsdf['EVENT_TYPE'] == 'Made Shot') & (shotsdf['TEAM_NAME'] == team)]['LOC_X'],
        y = shotsdf[(shotsdf['EVENT_TYPE'] == 'Made Shot') & (shotsdf['TEAM_NAME'] == team)]['LOC_Y'],
        mode = 'markers',
        marker = dict(
            size = 2,
            color = 'rgba(63, 191, 63, 0.9)',
        ), 
        name = 'Made',
        text = shotsdf[(shotsdf['EVENT_TYPE'] == 'Made Shot') & (shotsdf['TEAM_NAME'] == team)]['PLAYER_NAME'],
        textposition = 'top left',
        textfont = dict(
            color = 'rgba(75, 85, 102,0.7)'
        ),
        visible = (team =='Cle')
    )

    shot_trace_missed = go.Scatter(
        x = shotsdf[(shotsdf['EVENT_TYPE'] == 'Missed Shot') & (shotsdf['TEAM_NAME'] == team)]['LOC_X'],
        y = shotsdf[(shotsdf['EVENT_TYPE'] == 'Missed Shot') & (shotsdf['TEAM_NAME'] == team)]['LOC_Y'],
        mode = 'markers',
        marker = dict(
            size = 2,
            color = 'rgba(241, 18, 18, 0.9)',
        ), 
        name = 'Missed',
        text = shotsdf[(shotsdf['EVENT_TYPE'] == 'Missed Shot') & (shotsdf['TEAM_NAME'] == team)]['PLAYER_NAME'],
        textposition = 'top left',
        textfont = dict(
            color = 'rgba(75, 85, 102,0.7)'
        ),
        visible = (team =='Cle')
    )

    shot_zones_text = go.Scatter(
        x=[-175, 0, 175, -120, 0, 120, -190, -135, 0, 0, 135, 190],
        y=[250, 300, 250, 140, 200, 140, -25, 40, 90, -10, 40, -25],
        mode='text',
        name='FG %',
        text=[getZoneText(team, 'left_center_3'), 
              getZoneText(team, 'center_3'), 
              getZoneText(team, 'right_center_3'), 
              getZoneText(team, 'left_center_mid'), 
              getZoneText(team, 'center_mid'), 
              getZoneText(team, 'right_center_mid'), 
              getZoneText(team, 'left_corner_3'), 
              getZoneText(team, 'left_mid'), 
              getZoneText(team, 'paint'), 
              getZoneText(team, 'restricted_area'), 
              getZoneText(team, 'right_mid'), 
              getZoneText(team, 'right_corner_3')],
        textposition='top center',        
        textfont = dict(
            color = 'rgba(10, 10, 10, 1)',
            size = 14
        ),
        visible = (team == 'Cle')
    )
    
    data.append(shot_trace_made)
    data.append(shot_trace_missed)
    data.append(shot_zones_text)
    
    buttons_data.append(
        dict(
            label = team,
            method = 'update',
            args = [{'visible': updateVisibility(team)}, 
                    {'shapes': court_shapes + getZones()}]
        )
    )
    

updatemenus = list([
    dict(active=0,
         buttons = buttons_data,
         direction = 'down',
         pad = {'r': 10, 't': 10},
         showactive = True,
         x = 0.21,
         xanchor = 'left',
         y = 1.19,
         yanchor = 'top',
         font = dict (
             size = 14
         )
    )
])

layout = go.Layout(
    title='Shot Chart for',
    titlefont=dict(
        size=14
    ),
    hovermode = 'closest',
    updatemenus = updatemenus,
    showlegend = True,
    height = 600,
    width = 600, 
    shapes = court_shapes+zone_shapes,
    xaxis = dict(
        showticklabels = False,
        range = [-250, 250]
    ),
    yaxis = dict(
        showticklabels = False,
        range = [-47.5, 452.5]
    )
)
 
fig = go.Figure(data=data, layout=layout)
iplot(fig)
In [ ]: